/**
 * @file .
 * @author wangxiaowei0303@163.com
 */

#include <math.h>

#include <algorithm>

#include "Alphatrimmed.h"
#include "../string_util.h"


/* this->d 呈现给用户的名称. */
#define D_ARG "d"

void 
Alphatrimmed::help(std::string &buf) const
{
    buf.append(
        "修正的 Alpha 均值滤波器;适合处理包含多种噪声的情况;\n"
        "如同时存在高斯噪声,脉冲噪声.\n"
        "d;在进行均值之前,会移除前 d/2 个最低元素,以及最大元素;\n"
        "  unsinged int 类型,应该为偶数.\n"
    );
    Filter::help(buf);
    return ;
}

void
Alphatrimmed::set(const char *argname,const char *argval)
{
    if (strEqual(argname,D_ARG)) { 
        this->d = atoi(argval);
        if (isOdd(this->d)) 
            handleInvalidArgVal(__PRETTY_FUNCTION__,argname,argval);
    } else { 
        Filter::set(argname,argval);
    }
    return ;
}

const char*
Alphatrimmed::get(const char *argname,std::string &buf) const
{
    size_t oldSize = buf.size();
    if (strEqual(argname,D_ARG)) 
        addFormat(buf,"%u",this->d);
    else 
       return Filter::get(argname,buf);
    return buf.data() + oldSize;
}

void
Alphatrimmed::getSupportedArgs(
    std::vector<std::string> &args) const
{
    args.push_back(D_ARG);
    Filter::getSupportedArgs(args);
    return ;
}

double
Alphatrimmed::operOnNeigh(const cv::Mat &neigh)
{
    cv::Mat n = neigh.clone();
    /*
     * 考虑到该函数是一个会被频繁调用的函数,所以并没有在这里考虑到 d 的合法性,
     * 即 d 应该 < neigh.rows * neigh.cols;考虑到在 set() 时会检测 d 为偶数,并
     * 且 neigh.rows,neigh.cols 为奇数,因此 d 一定不会等于 rows * cols.
     * 当 d > rows * cols,该函数返回 0.
     */
    std::sort(n.begin<uchar>(),n.end<uchar>());
    
    cv::MatConstIterator_<uchar> iter = n.begin<uchar>();
    cv::MatConstIterator_<uchar> end = n.end<uchar>();
    iter += this->d / 2;
    end -= this->d / 2;
    
    double sum = 0.0;
    for (; iter < end; ++iter) /* 此时不能使用 iter != end 来判断.  */
        sum += *iter;
    return sum / (n.rows * n.cols - this->d);
}

NOISE_ALGO_REGISTER("Alphatrimmed",Alphatrimmed);
